#include "GXHT30.h"

struct GXHT30_INFO GXHT30_Info;

int GXHT_IIC_INIT(){
    IoTGpioInit(GPIO_SCL);
    IoTGpioSetFunc(GPIO_SCL,IOT_GPIO_FUNC_GPIO_9_I2C0_SCL);

    IoTGpioInit(GPIO_SDA);
    IoTGpioSetFunc(GPIO_SDA,IOT_GPIO_FUNC_GPIO_10_I2C0_SDA);

    IoTI2cInit(IIC_id, I2C_BAUDRATE);

    printf("I2C0 INIT SUCCESS!\r\n");
}

int GXHT_INIT(){
    int ret;
    uint8_t send_data[2] = { 0x22, 0x36 };
    ret = IoTI2cWrite(IIC_id, (Deviece_Address << 1) | 0x00, send_data, sizeof(send_data));
    if (ret != 0) {
        printf("===== Error: I2C write ret = 0x%x! =====\r\n", ret);
        return -1;
    }
    return 0;
}

float GXHT3xCalcTemperatureC(uint16_t u16sT){
     float temperatureC = 0; // variable for result
    u16sT &= ~0x0003;       // clear bits [1..0] (status bits)
    // -- calculate temperature [℃] --
    temperatureC = (175 * (float)u16sT / 0xffff - 45); // T = -45 + 175 * rawValue / (2^16-1)
    return temperatureC;

}

float GXHT3xCalcRH(uint16_t u16sRH){
    float humidityRH = 0; // variable for result
    u16sRH &= ~0x0003;    // clear bits [1..0] (status bits)
    // -- calculate relative humidity [%RH] --
    humidityRH = (100 * (float)u16sRH / 0xffff); // RH = rawValue / (2^16-1) * 10
    return humidityRH;

}

uint8_t GXHT3xCheckCrc(uint8_t data[], uint8_t nbrOfBytes, uint8_t checksum){
    uint8_t crc = 0xFF;
    uint8_t bit = 0;
    uint8_t byteCtr;
    const int16_t POLYNOMIAL = 0x131;
    // calculates 8-Bit checksum with given polynomial
    for (byteCtr = 0; byteCtr < nbrOfBytes; ++byteCtr) {
        crc ^= (data[byteCtr]);
        for (bit = 8; bit > 0; --bit) {
            if (crc & 0x80)
                crc = (crc << 1) ^ POLYNOMIAL;
            else
                crc = (crc << 1);
        }
    }

    if (crc != checksum)
        return 1;
    else
        return 0;
}

void GXHT_Read_Data(){
    int ret;
    uint16_t temp = 0;
    uint16_t humi = 0;
    uint32_t status = 0;
    uint16_t dat, tmp;
    uint8_t GXHT3X_Data_Buffer[6];
    uint8_t data[3];

    IotI2cData GXHT30_i2c_data = { 0 };
    uint8_t send_data[2] = { 0xE0, 0x00 };
    GXHT30_i2c_data.sendBuf = send_data;
    GXHT30_i2c_data.sendLen = sizeof(send_data);
    GXHT30_i2c_data.receiveBuf = GXHT3X_Data_Buffer;
    GXHT30_i2c_data.receiveLen = sizeof(GXHT3X_Data_Buffer);

    ret = IoTI2cWriteread(IIC_id, (Deviece_Address << 1) | 0x00, &GXHT30_i2c_data); // Read bh1750 sensor data
    if (ret != 0) {
        printf("===== Error: I2C read status = 0x%x! =====\r\n", status);
        return -1;
    }

    data[0] = GXHT3X_Data_Buffer[0];
    data[1] = GXHT3X_Data_Buffer[1];
    data[2] = GXHT3X_Data_Buffer[2];

    tmp = GXHT3xCheckCrc(data, 2, data[2]);
    if (!tmp) {
        dat = ((uint16_t)data[0] << 8) | data[1];
        GXHT30_Info.tempreture = GXHT3xCalcTemperatureC(dat);
    }
    data[0] = GXHT3X_Data_Buffer[3];
    data[1] = GXHT3X_Data_Buffer[4];
    data[2] = GXHT3X_Data_Buffer[5];
 
    tmp = GXHT3xCheckCrc(data, 2, data[2]);
    if (!tmp) {
        dat = ((uint16_t)data[0] << 8) | data[1];
        GXHT30_Info.humidity = GXHT3xCalcRH(dat);
    }
    return 0;

}

void GXHT_Task(){
    GXHT_IIC_INIT();
    int ret;
    ret = GXHT_INIT();
    if (ret != 0) {
        printf("Init GXHT30 failed!\r\n");
        return 0;
    }

    while(1){
        printf("=======================================\n");
        printf("***********GXHT30_TASK**********\n");
        printf("=======================================\n");
        GXHT_Read_Data();
        printf("Tem = %.2f, humi = %.2f\r\n",GXHT30_Info.tempreture,GXHT30_Info.humidity);
        usleep(1000000);
    }
}


void GXHT_Entry(void){
    osThreadAttr_t attr;

    attr.name = "GXHT_Entry";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = (1024 * 8);
    attr.priority = 25;

    if (osThreadNew((osThreadFunc_t)GXHT_Task, NULL, &attr) == NULL) {
        printf("Falied to create GXHT_Task!\n");
    }

}